這篇寫完就還剩五篇,今天來完成 HackMD 的 API 串接部份
val hackmdApiKey: Flow<String> = context.dataStore.data
.map { preferences ->
preferences[Keys.hackmdApiKey] ?: ""
}
suspend fun setHackmdApiKey(apiKey: String) {
context.dataStore.edit { preferences ->
preferences[Keys.hackmdApiKey] = apiKey
}
}
suspend fun clearHackmdApiKey() {
context.dataStore.edit { preferences ->
preferences.remove(Keys.hackmdApiKey)
}
}
class GetHackmdApiKeyUseCase @Inject constructor(
private val repository: UserPreferencesRepository
) {
operator fun invoke(): Flow<String> {
return repository.hackmdApiKey
}
}
class SaveHackmdApiKeyUseCase @Inject constructor(
private val repository: UserPreferencesRepository
) {
suspend operator fun invoke(apiKey: String) {
repository.setHackmdApiKey(apiKey)
}
}
class ClearHackmdApiKeyUseCase @Inject constructor(
private val repository: UserPreferencesRepository
) {
suspend operator fun invoke() {
repository.clearHackmdApiKey()
}
}
val uiState: StateFlow<SettingsUiState> = combine(
getSettingsUseCase(),
getHackmdApiKeyUseCase()
) { settings, apiKey ->
SettingsUiState(
settings = settings,
hackmdApiKey = apiKey,
isLoading = false
)
}.stateIn(
scope = viewModelScope,
started = SharingStarted.WhileSubscribed(5000),
initialValue = SettingsUiState(isLoading = true)
)
fun onHackmdApiKeyChanged(apiKey: String) {
viewModelScope.launch {
saveHackmdApiKeyUseCase(apiKey)
}
}
fun onClearHackmdApiKey() {
viewModelScope.launch {
clearHackmdApiKeyUseCase()
}
}
Spacer(modifier = Modifier.height(16.dp))
// HackMD Section
Text(
text = "HackMD 整合",
style = MaterialTheme.typography.titleLarge
)
Button(onClick = { uriHandler.openUri("https://hackmd.io/") }) {
Text("前往 HackMD 官網")
}
Button(onClick = { uriHandler.openUri("https://hackmd.io/@docs/issue-revoke-api-token-zh") }) {
Text("如何取得 Token?")
}
val isApiKeySet = uiState.hackmdApiKey.isNotBlank()
TextField(
value = uiState.hackmdApiKey,
onValueChange = onApiKeyChanged,
label = { Text("HackMD API Token") },
modifier = Modifier.fillMaxWidth(),
readOnly = isApiKeySet,
visualTransformation = if (isApiKeySet) PasswordVisualTransformation() else VisualTransformation.None,
trailingIcon = {
if (isApiKeySet) {
IconButton(onClick = onClearApiKey) {
Icon(
imageVector = Icons.Default.Clear,
contentDescription = "清除 API Token"
)
}
}
}
)